/* tcpgetdata.c - tcpgetdata */

#include "tcb.h"

/*------------------------------------------------------------------------
 *  tcpgetdata  -  copy data from a TCP receive buffer to a user buffer
 *------------------------------------------------------------------------
 */
int tcpgetdata(struct tcb *ptcb, u_char *pch, unsigned len)
{
    tcpseq	seq;
    unsigned	cc;

    seq = ptcb->tcb_rnext - ptcb->tcb_rbcount; /* start sequence	*/
    if (ptcb->tcb_flags & TCBF_RUPOK) {
        int nbc, ubc;	/* normal & urgent byte counts	*/

        nbc = ptcb->tcb_rnext - ptcb->tcb_rupseq - 1;
        if (nbc >= 0) {		/* urgent boundary in buffer	*/
            ubc = ptcb->tcb_rbcount - nbc;
            if ((int)len >= ubc) {
                len = ubc;
                ptcb->tcb_flags &= ~TCBF_RUPOK;
            }
        }
    }
    for (cc=0; ptcb->tcb_rbcount && cc < len;) {
        *pch++ = ptcb->tcb_rcvbuf[ptcb->tcb_rbstart];
        --ptcb->tcb_rbcount;
        if (++ptcb->tcb_rbstart >= ptcb->tcb_rbsize)
            ptcb->tcb_rbstart = 0;
        ++cc;
    }
    if (ptcb->tcb_rbcount == 0)
        ptcb->tcb_flags &= ~TCBF_PUSH;
    /*
     * open the receive window, if it's closed and we've made
     * enough space to fit a segment.
     */
    if (SEQCMP(ptcb->tcb_cwin, ptcb->tcb_rnext) <= 0 && tcprwindow(ptcb)) {
        ptcb->tcb_flags |= TCBF_NEEDOUT;
        tcpkick(ptcb);
    }
    return cc;
}
